using System;
using JetBrains.Metadata.Reader.API;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.UnitTestExplorer;

namespace JamesKovacs.ReSharper.UnitTestSupport.VstsUnit {
    internal class VstsAssemblyExplorer {
        private readonly IUnitTestProvider m_Provider;
        private readonly UnitTestElementConsumer m_Consumer;
        private readonly IMetadataAssembly m_Assembly;
        private readonly IProject m_Project;

        public VstsAssemblyExplorer(IUnitTestProvider provider, UnitTestElementConsumer consumer, IMetadataAssembly assembly, IProject project) {
            m_Provider = provider;
            m_Consumer = consumer;
            m_Assembly = assembly;
            m_Project = project;
        }

        public void Explore() {
            foreach(IMetadataTypeInfo typeInfo in m_Assembly.GetTypes()) {
                if(VstsUnitTestInspector.IsTestFixture(typeInfo)) {
                    VstsUnitTestFixtureElement fixture = new VstsUnitTestFixtureElement(m_Provider, m_Project, typeInfo.FullyQualifiedName, m_Assembly.Location);
                    if(VstsUnitTestInspector.IsIgnored(typeInfo)) {
                        fixture.SetExplicit(string.Empty);
                    }
                    m_Consumer(fixture);
                    int order = 0;
                    foreach(IMetadataMethod methodInfo in GetAllTestMethods(typeInfo)) {
                        if(VstsUnitTestInspector.IsTestMethod(methodInfo)) {
                            VstsUnitTestElement testElement = new VstsUnitTestElement(m_Provider, fixture, m_Project, methodInfo.DeclaringType.FullyQualifiedName, methodInfo.Name, order++);
                            if(VstsUnitTestInspector.IsIgnored(methodInfo)) {
                                testElement.SetExplicit(string.Empty);
                            }
                            m_Consumer(testElement);
                        }
                    }
                }
            }
        }

        private static IMetadataMethod[] GetAllTestMethods(IMetadataTypeInfo typeInfo) {
            return Array.FindAll(typeInfo.GetMethods(),
                                 delegate(IMetadataMethod method) { return VstsUnitTestInspector.IsTestMethod(method); });
        }
    }
}